package com.aionengine.gameserver.services.custom;

import com.aionemu.commons.services.CronService;
import com.aionemu.commons.utils.Rnd;
import com.aionengine.gameserver.model.ChatType;
import com.aionengine.gameserver.model.Race;
import com.aionengine.gameserver.model.TeleportAnimation;
import com.aionengine.gameserver.model.gameobjects.player.Player;
import com.aionengine.gameserver.network.aion.serverpackets.SM_SKILL_COOLDOWN;
import com.aionengine.gameserver.services.abyss.AbyssPointsService;
import com.aionengine.gameserver.services.item.ItemService;
import com.aionengine.gameserver.services.teleport.TeleportService2;
import com.aionengine.gameserver.skillengine.SkillEngine;
import com.aionengine.gameserver.skillengine.model.SkillTargetSlot;
import com.aionengine.gameserver.utils.PacketSendUtility;
import com.aionengine.gameserver.utils.ThreadPoolManager;
import com.aionengine.gameserver.world.InstanceType;
import com.aionengine.gameserver.world.World;
import com.aionengine.gameserver.world.WorldMap;
import com.aionengine.gameserver.world.WorldMapInstance;
import com.aionengine.gameserver.world.WorldMapInstanceFactory;
import com.aionengine.gameserver.world.WorldMapType;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author BlackCore
 */
public class FFAManager {
    
    private static final WorldMapType FFA_INSTANCE_MAP = WorldMapType.NOCHSANA_TRAINING_CAMP;
	private static final int FFA_INSTANCE_ID = 99;
	private static boolean isAvailable;      
	private static final Logger log = LoggerFactory.getLogger(FFAManager.class);
	public static void start(){
        isAvailable=true;
        sendFFAStatus(" Batalla Libre para todos Disponible, Use comando: .ffa enter.");
    }
    public static void stop(){
        isAvailable = false;
        sendFFAStatus(" Batalla Libre para todos ha sido detenido a la fuerza.");
        for (Player p : FFAInstance().getPlayersInside()) {
                 TeleportService2.moveToBindLocation(p, true);
        }
    }
	
	public static void startFFaTask() {
		String time = "0 0 0/1 1/1 * ? *";
		CronService.getInstance().schedule(new Runnable() {
			@Override
			public void run() {
                log.info("FFA Tarea de evento ha iniciado!");
				DateTime now = DateTime.now();
				int hour = now.getHourOfDay();
				if (hour == 19) {
					isAvailable = true;
					sendFFAStatus(" Batalla Libre FFA Disponible, Use comando: .ffa enter");
					//FFA Spawn Home
					ThreadPoolManager.getInstance().schedule(new Runnable() {
						@Override
						public void run() {
							sendFFAStatus(" Dentro de 10 minutos aparecera un cofre del tesoro en la zona FFA");
							ThreadPoolManager.getInstance().schedule(new Runnable() {
								@Override
								public void run() {
									sendFFAStatus(" Cofre del tesoso ha aparecido en la zona FFA");
									CustomSPAWN.spawnFarmMobsForFFA();
								}
							}, 10 * 60 * 1000);
						}
					}, 5 * 60 * 1000);
					//FFA Spawn End
					} else {                                
					isAvailable = false;
					for (Player p: FFAInstance().getPlayersInside()) {
					TeleportService2.moveToBindLocation(p, true);
					p.setFFAkills(0);
					}
				}
			}

		}, time);
	}
		
	public synchronized static WorldMapInstance getFFAInstance() {
		WorldMap map = World.getInstance().getWorldMap(FFA_INSTANCE_MAP.getId());

		log.info("Creando nueva FFAinstance:" + FFA_INSTANCE_MAP + " id:" + FFA_INSTANCE_ID + " owner:" + 0);
		WorldMapInstance worldMapInstance = WorldMapInstanceFactory.createWorldMapInstance(map, FFA_INSTANCE_ID, 0, InstanceType.FFA);

		map.addInstance(FFA_INSTANCE_ID, worldMapInstance);
		startFFaTask();
		CustomSPAWN.spawnFarmHealForFFA();
		return worldMapInstance;
	}
	
	public static WorldMapInstance FFAInstance() {
		return World.getInstance().getWorldMap(FFA_INSTANCE_MAP.getId()).getWorldMapInstanceById(FFA_INSTANCE_ID);
	}
	
	public static boolean isInFFA(Player player) {
		return player.getPosition().getWorldMapInstance().isFFAInstance();
	}
	
    public static void rCd (Player p){
            List<Integer> delayIds = new ArrayList<Integer>();
				if (p.getSkillCoolDowns() != null) {
					long currentTime = System.currentTimeMillis();
					for (Map.Entry<Integer, Long> en : p.getSkillCoolDowns().entrySet())
						delayIds.add(en.getKey());

					for (Integer delayId : delayIds)
						p.setSkillCoolDown(delayId, currentTime);

					delayIds.clear();
					PacketSendUtility.sendPacket(p, new SM_SKILL_COOLDOWN(p.getSkillCoolDowns()));
				}
            
     }
	
	public static void onKill(Player killer, Player victim) {
		if (isInFFA(killer)) {
			victim.getEffectController().removeAbnormalEffectsByTargetSlot(SkillTargetSlot.DEBUFF);
			killer.increaseFFAkills();
			checkBonusEffect(killer);
		}
	}
	
	public static void onLogOut(Player player) {
		if (isInFFA(player)) {
			player.setFFAkills(0);
			TeleportService2.teleportToCapital(player);
		}
	}
	
	public static void onRevive(Player player) {
            if(!FFAManager.isAvailable() == true) {
                TeleportService2.moveToBindLocation(player, true);
                return;
            } else {
            rndTp(player);
            player.getKnownList().doUpdate();
            player.getEffectController().removeAbnormalEffectsByTargetSlot(SkillTargetSlot.DEBUFF);
            SkillEngine.getInstance().applyEffectDirectly(18191, player, player, 15000); //Escudo
            SkillEngine.getInstance().applyEffectDirectly(10380, player, player, 11000); //Paralizar
            }
	}
        
	private static int vipRewardItems [] = {186000242, 186000147,186000096,186000030,186000237,186000137};
	private static int StandardRewardItems [] = {164002116,164002117,164002118,164002119,164002120,182005205};
	private static void checkBonusEffect(Player killer) {
            
		int kills = killer.getFFAkills();
        if(FFAManager.FFAInstance().getPlayersInside().size()<=15){
		switch (kills) {
                    case 5:
                       AbyssPointsService.addAp(killer, 1000);
                       ItemService.addItem(killer, vipRewardItems[Rnd.get(0, vipRewardItems.length -1)], 1);
                       PacketSendUtility.sendMessage(killer,"[Weakling] una serie de asesinatos!");
                       break;
                   case 15:
                       AbyssPointsService.addAp(killer, 3000);
                       ItemService.addItem(killer, vipRewardItems[Rnd.get(0, vipRewardItems.length -1)], 1);
                       PacketSendUtility.sendMessage(killer, "[Experienced] eliminados consecutivamente");
                       break;
                   case 25:
                       AbyssPointsService.addAp(killer, 5000);
                       ItemService.addItem(killer, vipRewardItems[Rnd.get(0, vipRewardItems.length -1)], 1);
                       SkillEngine.getInstance().applyEffectDirectly(10406, killer, killer, 0);
                       PacketSendUtility.sendMessage(killer, "[Monsterkill] Consigue una bendicion!");
                       break;
                   case 30:
                	   switch (killer.getRace()) {
                		   case ASMODIANS:
                			   SkillEngine.getInstance().applyEffectDirectly(10406, killer, killer, 15000);
                			   break;
                		   case ELYOS:
                			   SkillEngine.getInstance().applyEffectDirectly(10405, killer, killer, 15000);
                			   break;
                }
		       broadcastMessage(killer, " Guerrero " + killer.getName() + "  mato  " + kills + " enemigos, su velocidad y fuerza aumentan.");
		       break;
                    default:
                        AbyssPointsService.addAp(killer, 150);
                        ItemService.addItem(killer, StandardRewardItems[Rnd.get(0, StandardRewardItems.length -1)], 1);
                        PacketSendUtility.sendYellowMessage(killer, "Has recibido el premio estandar de FFA.");
                        break;
                      }
                }
                if(FFAManager.FFAInstance().getPlayersInside().size()>15){
                    switch (kills) {
                    case 5:
                       AbyssPointsService.addAp(killer, 1000);
                       ItemService.addItem(killer, vipRewardItems[Rnd.get(0, vipRewardItems.length -1)], 1);
                       PacketSendUtility.sendMessage(killer,"[Weakling] una serie de asesinatos!");
                       break;
                   case 15:
                       AbyssPointsService.addAp(killer, 3000);
                       ItemService.addItem(killer, vipRewardItems[Rnd.get(0, vipRewardItems.length -1)], 1);
                       PacketSendUtility.sendMessage(killer, "[Experienced] eliminados consecutivamente");
                       break;
                   case 25:
                       AbyssPointsService.addAp(killer, 5000);
                       ItemService.addItem(killer, vipRewardItems[Rnd.get(0, vipRewardItems.length -1)], 1);
                       SkillEngine.getInstance().applyEffectDirectly(10406, killer, killer, 15);
                       PacketSendUtility.sendMessage(killer, "[Ripper] Consigue una bendicion!");
                       break;
		    case 30:
                        ItemService.addItem(killer, vipRewardItems[Rnd.get(0, vipRewardItems.length -1)], 1);
		        switch (killer.getRace()) {
                    case ASMODIANS:
                        SkillEngine.getInstance().applyEffectDirectly(10406, killer, killer, 25000);
                        break;
                    case ELYOS:
                        SkillEngine.getInstance().applyEffectDirectly(10405, killer, killer, 25000);
                        break;
                }
		       broadcastMessage(killer, " Guerrero " + killer.getName() + "  mato  " + kills	+ " enemigos, su velocidad y fuerza aumentan.");
		       break;
                    default:
                        AbyssPointsService.addAp(killer, 150);
                        ItemService.addItem(killer, StandardRewardItems[Rnd.get(0, StandardRewardItems.length -1)], 1);
                        PacketSendUtility.sendYellowMessage(killer, "Has recibido el premio estandar de FFA.");
                        break;
		}
                    
                }
                if(FFAManager.FFAInstance().getPlayersInside().size()>25){
                    switch (kills) {
                    case 5:
                       AbyssPointsService.addAp(killer, 1000);
                       ItemService.addItem(killer, vipRewardItems[Rnd.get(0, vipRewardItems.length -1)], 1);
                       PacketSendUtility.sendMessage(killer,"[Слабак]серия убийств!");
                       break;
                   case 15:
                       AbyssPointsService.addAp(killer, 3000);
                       ItemService.addItem(killer, vipRewardItems[Rnd.get(0, vipRewardItems.length -1)], 1);
                       PacketSendUtility.sendMessage(killer, "[Бывалый]Серия убийств");
                       break;
                   case 25:
                       AbyssPointsService.addAp(killer, 5000);
                       ItemService.addItem(killer, vipRewardItems[Rnd.get(0, vipRewardItems.length -1)], 1);
                       SkillEngine.getInstance().applyEffectDirectly(10406, killer, killer, 15);
                       PacketSendUtility.sendMessage(killer, "[Потрошитель]Получите благословление!");
                       break;
		    case 30:
                        ItemService.addItem(killer, vipRewardItems[Rnd.get(0, vipRewardItems.length -1)], 1);
		        switch (killer.getRace()) {
                    case ASMODIANS:
                        SkillEngine.getInstance().applyEffectDirectly(10406, killer, killer, 25000);
                        break;
                    case ELYOS:
                        SkillEngine.getInstance().applyEffectDirectly(10405, killer, killer, 25000);
                        break;
                }
		       broadcastMessage(killer, " Воин " + killer.getName() + "  убил  " + kills	+ " врагов и его скорость и сила увеличилась.");
		       break;
                    default:
                        AbyssPointsService.addAp(killer, 200);
                        //ItemService.addItem(killer, vipRewardItems[Rnd.get(0, vipRewardItems.length -1)], 1);
                        PacketSendUtility.sendYellowMessage(killer, "Вы получили стандартную награду в FFA локации.");
                        break;
		}
                    
                }
                
                if(kills==32){
                    if(FFAManager.FFAInstance().getPlayersInside().size()>20){
                        AbyssPointsService.addAp(killer, 3000);
                        PacketSendUtility.sendMessage(killer, "Tienes un bono extra!");
                    }
                    killer.setFFAkills(0);
                    PacketSendUtility.sendMessage(killer, "Usted ha hecho 32 asesinatos, sorprendente!");
                }
	}
		
	public static void onEnterFFA(Player player) {
		if (isInFFA(player) && !player.isGM())
                    if(FFAInstance().getPlayersInside().size()<=15){
			broadcastMessage(player, " Jugador " + player.getName() + " ha entrado en al FFA");}
                    if(FFAInstance().getPlayersInside().size()>15){
                        broadcastMessage(player, " Jugador " + player.getName() + " ha entrado al FFA, " + FFAInstance().getPlayersInside().size() + " jugadores, obtienen una recompensa mayor.");    
                    }
                    if(FFAInstance().getPlayersInside().size()>25){
                        broadcastMessage(player, " Jugador " + player.getName() + " ha entrado al FFA, " +FFAInstance().getPlayersInside().size() + " jugadores, obtienen una recompensa mucho mejor.");    
                    }
	}
        public static void onLeaveFFA(Player player){
            if(isInFFA(player) && !player.isGM())
                broadcastMessage(player," Jugador "  +player.getName() +  "  se fue del FFA!");
                player.setFFAkills(0);
        }
	
	private static void broadcastMessage(Player killer, final String message) {
        Iterator<Player> iter = killer.getPosition().getWorldMapInstance().playerIterator();
        while (iter.hasNext()) {
            Player player = iter.next();
            PacketSendUtility.sendMessage(player, "FFAManager", message, ChatType.GROUP_LEADER);
        }
    }

    public static void sendFFAStatus(String msg) {
        Iterator<Player> iter = World.getInstance().getPlayersIterator();
        while (iter.hasNext()) {
            PacketSendUtility.sendBrightYellowMessageOnCenter(iter.next(), "FFAManager:" + msg);
        }
    }
        
       public static void rndTpAnimation(Player player){
           float[] rnd = floats.get(Rnd.get(0, floats.size() - 1));
                TeleportService2.teleportTo(player, FFAManager.getFFAInstanceMap().getId(), FFAManager.getFFAInstanceId(), rnd[0], rnd[1], rnd[2], (byte) 0, TeleportAnimation.BEAM_ANIMATION);
       }
        
        public static void rndTp(Player player){
            float[] rnd = floats.get(Rnd.get(0, floats.size() - 1));
                TeleportService2.teleportTo(player, FFAManager.getFFAInstanceMap().getId(), FFAManager.getFFAInstanceId(), rnd[0], rnd[1], rnd[2], (byte) 0, TeleportAnimation.BEAM_ANIMATION);
            
        }
	private static List<float[]> floats = new ArrayList<float[]>(Arrays.asList(
		/**new float[]{578.4119f, 314.7861f, 271.28467f,0f},
        new float[]{728.937f, 230.45065f, 322.39825f},
        new float[]{805.84625f, 302.5921f, 322.39825f},
        new float[]{751.57526f, 422.58865f, 274.52502f},
        new float[]{693.2688f, 519.80426f, 279.93805f}));*/
		/** Silentera: new float[]{1232.1934f, 643.2736f, 346.50525f,0f},
        new float[]{782.1803f, 245.27728f, 334.36194f},
        new float[]{518.07336f, 324.08914f, 324.2739f},
        new float[]{481.87463f, 534.8375f, 327.9411f},
        new float[]{746.7448f, 1141.4602f, 326.57535f}));*/
		/**new float[]{284.6387f, 521.6247f, 223.37486f,0f},
        new float[]{284.14532f, 479.7763f, 222.94553f},
        new float[]{273.91187f, 501.17197f, 228.99596f},
        new float[]{285.9778f, 491.07727f, 224.96329f},
        new float[]{286.5255f, 509.68094f, 223.37134f}));*/
		new float[]{409.6671f, 505.7087f, 367.03918f,0f},
        new float[]{476.21997f, 544.296f, 361.74725f},
        new float[]{352.26505f, 417.04742f, 378.96838f},
        new float[]{344.86636f, 354.1116f, 393.93304f},
        new float[]{326.929f, 245.31943f, 411.3522f},
        new float[]{332.03113f, 594.0632f, 370.49805f},
        new float[]{412.4465f, 663.8798f, 362.48285f},
        new float[]{512.4842f, 667.55334f, 331.09473f},
        new float[]{309.46545f, 444.23862f, 367.64496f},
        new float[]{336.273f, 299.48718f, 403.3898f}));
        
        public static int getMorph(Player player) {
        int[] FFA_MORPH_ELY = {202514, 202515, 202516, 202517, 202518, 202529, 202531, 202537, 202539, 202541, 202543, 202547, 202549, 202551, 202585};
        int[] FFA_MORPH_ASMO = {202519, 202520, 202521, 202522, 202523, 202530, 202532, 202538, 202540, 202542, 202544, 202548, 202550, 202552, 202586};
        return (player.getRace() == Race.ASMODIANS ? FFA_MORPH_ASMO[Rnd.get(FFA_MORPH_ASMO.length)] : FFA_MORPH_ELY[Rnd.get(FFA_MORPH_ELY.length)]);
    }
        
	/**
	 * @return the ffaInstanceMap
	 */
	public static WorldMapType getFFAInstanceMap() {
		return FFA_INSTANCE_MAP;
	}
	
	public static int getFFAInstanceId() {
		return FFA_INSTANCE_ID;
	}

	public static boolean isAvailable() {
		return isAvailable;
	}
}
    

